﻿using System;
using System.Management;

namespace ClusterAwareProperties
{
    /// <summary>
    /// Convert a Cluster ManagementObject to Cluster Class
    /// </summary>
    public static class ClusterTranslate
    {
        /// <summary>
        /// Convert Cluster ManagementObject to Cluster Class
        /// </summary>
        /// <param name="clsClus">Group class</param>
        /// <param name="queryObj">ManagementObject Cluster</param>
        /// <returns>Cluster class with properties converted</returns>
        public static ClusterProperties Convert(this ClusterProperties clsClus, ManagementObject queryObj)
        {
            clsClus.AddEvictDelay = queryObj.PropertyValue<UInt32?>("AddEvictDelay");
            clsClus.AdminExtensions = queryObj.PropertyValue<string[]>("AdminExtensions");
            clsClus.BackupInProgress = queryObj.PropertyValue<UInt32?>("BackupInProgress");
            clsClus.Caption = queryObj.PropertyValue<string>("Caption");
            clsClus.ClusSvcHangTimeout = queryObj.PropertyValue<UInt32?>("ClusSvcHangTimeout");
            clsClus.ClusSvcRegroupOpeningTimeout = queryObj.PropertyValue<UInt32?>("ClusSvcRegroupOpeningTimeout");
            clsClus.ClusSvcRegroupPruningTimeout = queryObj.PropertyValue<UInt32?>("ClusSvcRegroupPruningTimeout");
            clsClus.ClusSvcRegroupStageTimeout = queryObj.PropertyValue<UInt32?>("ClusSvcRegroupStageTimeout");
            clsClus.ClusSvcRegroupTickInMilliseconds = queryObj.PropertyValue<UInt32?>("ClusSvcRegroupTickInMilliseconds");
            clsClus.ClusterGroupWaitDelay = queryObj.PropertyValue<UInt32?>("ClusterGroupWaitDelay");
            clsClus.ClusterLogLevel = queryObj.PropertyValue<UInt32?>("ClusterLogLevel");
            clsClus.ClusterLogSize = queryObj.PropertyValue<UInt32?>("ClusterLogSize");
            clsClus.CreationClassName = queryObj.PropertyValue<string>("CreationClassName");
            clsClus.CrossSubnetDelay = queryObj.PropertyValue<UInt32?>("CrossSubnetDelay");
            clsClus.CrossSubnetThreshold = queryObj.PropertyValue<UInt32?>("CrossSubnetThreshold");
            clsClus.Dedicated = queryObj.PropertyValue<UInt16[]>("Dedicated");
            clsClus.DefaultNetworkRole = queryObj.PropertyValue<UInt32>("DefaultNetworkRole");
            clsClus.Description = queryObj.PropertyValue<string>("Description");
            clsClus.EnableEventLogReplication = queryObj.PropertyValue<UInt32?>("EnableEventLogReplication");
            clsClus.EnableSharedVolumes = queryObj.PropertyEnum<UInt32, SharedVolumes>("EnableSharedVolumes", SharedVolumes.Unknown);
            clsClus.FixQuorum = queryObj.PropertyEnum<UInt32, FixQuorumState>("FixQuorum", FixQuorumState.Unknown);
            clsClus.GroupAdminExtensions = queryObj.PropertyValue<string[]>("GroupAdminExtensions");
            clsClus.HangRecoveryAction = queryObj.PropertyValue<UInt32?>("HangRecoveryAction");
            clsClus.IdentifyingDescriptions = queryObj.PropertyValue<string[]>("IdentifyingDescriptions");
            clsClus.IgnorePersistentStateOnStartup = queryObj.PropertyEnum<UInt32, IgnorePersistentState>("IgnorePersistentStateOnStartup", IgnorePersistentState.Unknown);
            clsClus.InstallDate = queryObj.PropertyValue<DateTime?>("InstallDate");
            clsClus.LogResourceControls = queryObj.PropertyValue<UInt32?>("LogResourceControls");
            clsClus.MaintenanceFile = queryObj.PropertyValue<string>("MaintenanceFile");
            clsClus.MaxNumberOfNodes = queryObj.PropertyValue<UInt32>("MaxNumberOfNodes");
            clsClus.Name = queryObj.PropertyValue<string>("Name");
            clsClus.NameFormat = queryObj.PropertyValue<string>("NameFormat");
            clsClus.NetworkAdminExtensions = queryObj.PropertyValue<string[]>("NetworkAdminExtensions");
            clsClus.NetworkInterfaceAdminExtensions = queryObj.PropertyValue<string[]>("NetworkInterfaceAdminExtensions");
            clsClus.NetworkPriorities = queryObj.PropertyValue<string[]>("NetworkPriorities");
            clsClus.NodeAdminExtensions = queryObj.PropertyValue<string[]>("NodeAdminExtensions");
            clsClus.OtherIdentifyingInfo = queryObj.PropertyValue<string[]>("OtherIdentifyingInfo");
            clsClus.PlumbAllCrossSubnetRoutes = queryObj.PropertyValue<UInt32?>("PlumbAllCrossSubnetRoutes");
            clsClus.PrimaryOwnerContact = queryObj.PropertyValue<string>("PrimaryOwnerContact");
            clsClus.PrimaryOwnerName = queryObj.PropertyValue<string>("PrimaryOwnerName");
            clsClus.PrivateProperties = new PrivatePropertiesData(queryObj);
            clsClus.QuorumArbitrationTimeMax = queryObj.PropertyValue<UInt32>("QuorumArbitrationTimeMax");
            clsClus.QuorumArbitrationTimeMin = queryObj.PropertyValue<UInt32>("QuorumArbitrationTimeMin");
            clsClus.QuorumLogFileSize = queryObj.PropertyValue<UInt32?>("QuorumLogFileSize");
            clsClus.QuorumPath = queryObj.PropertyValue<string>("QuorumPath");
            try
            {
                var aux = queryObj.PropertyValue<string>("QuorumType").ToUpper().Replace(" ", "");
                switch (aux)
                {
                    case "MAJORITY":
                        clsClus.QuorumType = QuorumTypeEnum.Majority;
                        break;
                    case "NOMAJORITY":
                        clsClus.QuorumType = QuorumTypeEnum.NoMajority;
                        break;
                }
            }
            catch
            {
                clsClus.QuorumType = QuorumTypeEnum.Unknown;
            }
            clsClus.RequestReplyTimeout = queryObj.PropertyValue<UInt32?>("RequestReplyTimeout");
            clsClus.ResourceAdminExtensions = queryObj.PropertyValue<string[]>("ResourceAdminExtensions");
            clsClus.ResourceDllDeadlockPeriod = queryObj.PropertyValue<UInt32?>("ResourceDllDeadlockPeriod");
            clsClus.ResourceTypeAdminExtensions = queryObj.PropertyValue<string[]>("ResourceTypeAdminExtensions");
            clsClus.Roles = queryObj.PropertyValue<string[]>("Roles");
            clsClus.RootMemoryReserved = queryObj.PropertyValue<UInt32?>("RootMemoryReserved");
            clsClus.SameSubnetDelay = queryObj.PropertyValue<UInt32?>("SameSubnetDelay");
            clsClus.SameSubnetThreshold = queryObj.PropertyValue<UInt32?>("SameSubnetThreshold");
            clsClus.SecurityDescriptor = queryObj.PropertyValue<UInt16[]>("Security_Descriptor");
            clsClus.SecurityLevel = queryObj.PropertyEnum<UInt32, LevelSecurity>("SecurityLevel", LevelSecurity.Unknown);
            clsClus.SharedVolumeCompatibleFilters = queryObj.PropertyValue<string[]>("SharedVolumeCompatibleFilters");
            clsClus.SharedVolumeIncompatibleFilters = queryObj.PropertyValue<string[]>("SharedVolumeIncompatibleFilters");
            clsClus.SharedVolumesRoot = queryObj.PropertyValue<string>("SharedVolumesRoot");
            clsClus.ShutdownTimeoutInMinutes = queryObj.PropertyValue<UInt32?>("ShutdownTimeoutInMinutes");
            clsClus.Status = queryObj.PropertyEnum<string, StatusResource>("Status", StatusResource.Unknown);
            clsClus.WitnessDatabaseWriteTimeout = queryObj.PropertyValue<UInt32?>("WitnessDatabaseWriteTimeout");
            clsClus.WitnessRestartInterval = queryObj.PropertyValue<UInt32?>("WitnessRestartInterval");
            return clsClus;
        }

        ///<summary>
        /// Convert Cluster class to ManagementObject and Save on Cluster
        ///</summary>
        ///<param name="clsClus">Cluster class to converter</param>
        ///<param name="opSystem">Operational System where clster is running</param>
        public static void SaveManagementObject(this ClusterProperties clsClus, WindowsOperationSystem opSystem)
        {
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["AddEvictDelay"] = clsClus.AddEvictDelay;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["AdminExtensions"] = clsClus.AdminExtensions;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["BackupInProgress"] = clsClus.BackupInProgress;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["ClusterGroupWaitDelay"] = clsClus.ClusterGroupWaitDelay;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["ClusterLogLevel"] = clsClus.ClusterLogLevel;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["ClusterLogSize"] = clsClus.ClusterLogSize;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["CrossSubnetDelay"] = clsClus.CrossSubnetDelay;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["CrossSubnetThreshold"] = clsClus.CrossSubnetThreshold;
            }
            clsClus.Instance["DefaultNetworkRole"] = clsClus.DefaultNetworkRole;
            clsClus.Instance["Description"] = clsClus.Description;
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["EnableEventLogReplication"] = clsClus.EnableEventLogReplication;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["EnableSharedVolumes"] = (UInt32)clsClus.EnableSharedVolumes;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["GroupAdminExtensions"] = clsClus.GroupAdminExtensions;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["HangRecoveryAction"] = clsClus.HangRecoveryAction;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["LogResourceControls"] = clsClus.LogResourceControls;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["MaintenanceFile"] = clsClus.MaintenanceFile;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["NetworkAdminExtensions"] = clsClus.NetworkAdminExtensions;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["NetworkInterfaceAdminExtensions"] = clsClus.NetworkInterfaceAdminExtensions;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["NetworkPriorities"] = clsClus.NetworkPriorities;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["NodeAdminExtensions"] = clsClus.NodeAdminExtensions;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["PlumbAllCrossSubnetRoutes"] = clsClus.PlumbAllCrossSubnetRoutes;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["PrivateProperties"] = clsClus.PrivateProperties.ConvertToManagemenBasetObject();
            }
            try
            {
                clsClus.Instance["QuorumArbitrationTimeMax"] = clsClus.QuorumArbitrationTimeMax;
                clsClus.Instance["QuorumArbitrationTimeMin"] = clsClus.QuorumArbitrationTimeMin;
            }
            // ReSharper disable EmptyGeneralCatchClause
            catch
            // ReSharper restore EmptyGeneralCatchClause
            {
                //Not have Quorum
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["QuorumLogFileSize"] = clsClus.QuorumLogFileSize;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["RequestReplyTimeout"] = clsClus.RequestReplyTimeout;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["ResourceAdminExtensions"] = clsClus.ResourceAdminExtensions;
            }
            if (opSystem == WindowsOperationSystem.Windows2003 || opSystem == WindowsOperationSystem.Windows2003R2)
            {
                clsClus.Instance["ResourceTypeAdminExtensions"] = clsClus.ResourceTypeAdminExtensions;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["RootMemoryReserved"] = clsClus.RootMemoryReserved;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["SameSubnetDelay"] = clsClus.SameSubnetDelay;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["SameSubnetThreshold"] = clsClus.SameSubnetThreshold;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["SharedVolumeCompatibleFilters"] = clsClus.SharedVolumeCompatibleFilters;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["SharedVolumeIncompatibleFilters"] = clsClus.SharedVolumeIncompatibleFilters;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["ShutdownTimeoutInMinutes"] = clsClus.ShutdownTimeoutInMinutes;
            }
            if (opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["WitnessDatabaseWriteTimeout"] = clsClus.WitnessDatabaseWriteTimeout;
            }
            if (opSystem == WindowsOperationSystem.Windows2008 || opSystem == WindowsOperationSystem.Windows2008R2)
            {
                clsClus.Instance["WitnessRestartInterval"] = clsClus.WitnessRestartInterval;
            }
            clsClus.Instance.Put();
        }
    }
}
